#include <stdio.h>
#include <gmp.h>
#include <time.h>
#include <stdlib.h>
						/*algumas variaveis sao declaradas como long double e int. os ints sao utilizados dentro do loop para melhor desempenho, e depois sao copiadas em variaveis float, para que seja possivel fazer a divisao, que só aceita floats como argumento*/

int main (int argc, char *argv[]){
			
	mpf_t PI, mpf_count, mpf_it;		//PI, contador de pontos dentro do circulo e iterador
	mpz_t it, max_it, count;		//iterador, maximo de iteracoes e contador de pontos
	long double x, y;				//coordenadas x y do ponto
	FILE *file;				//arquivo de saida

	mpf_set_default_prec(35000000);         //precisao padrao: 35 milhoes de bits (aprox. 10 milhoes em decimal)
	mpf_inits(PI, mpf_count, mpf_it, NULL); //inicializa long doubles com a precisao acima
	mpz_inits(it, max_it, count, NULL);	//inicializa ints

	srand(time(NULL));			//semente de numeros aleatorios

	if(argc == 1){
		printf("Passe por linha de comando o numero de iteracoes.\n");
		return 0;
	}

	file = fopen("PImcarlosequencial", "w+");               //abre arquivo para escrita
	if(file == NULL){
		printf("Erro ao abrir o arquivo\n");
		return 0;
	}

	gmp_sscanf(argv[1], "%Zd", max_it);     //atribui a max_it o argumento da linha de comando

	printf("Iniciando calculo do pi com %s iteracoes pelo metodo de Monte Carlo sequencial.\n", argv[1]);
		
	for(mpz_set_ui(it, 0); mpz_cmp(it, max_it); mpz_add_ui(it, it, 1)){   //for(it=0;it<max_it;it++);
	
		x = ((long double) (RAND_MAX - rand()) /(long double) RAND_MAX); //sorteia um ponto
		y = ((long double) (RAND_MAX - rand()) /(long double) RAND_MAX);
	
		if( x*x + y*y <= 1.0 )             //checa se esse ponto ta dentro de um circulo de raio 1
			mpz_add_ui(count, count, 1); //count++
	}

	mpf_set_z(mpf_count, count);		//converte count e it para long double
	mpf_set_z(mpf_it, it);			
	
	mpf_mul_ui(mpf_count, mpf_count, 4);	//pi *= 4;
	mpf_div(PI, mpf_count, mpf_it);		//pi = count/it;

	printf("Calculo concluido.\nEscrevendo resultado em PImcarlosequencial\n");

        mpf_out_str(file, 10, 0, PI);		//imprime PI no arquivo em base 10, com precisao padrao
		
	fclose(file);
	file = NULL;				//fecha arquivo e limpa variaveis

	mpf_clears(mpf_count, mpf_it, PI, NULL);
	mpz_clears(it, max_it, count, NULL);

return 0;
}
